/* $Id: ClientRegistrationDelegateImpl.java 
 * Copyright (C) 2011, TRAKHEES
 *  
 * Revision History
 *
 * Date  			Author 		    	Remarks
 * ---------------------------------------------------------------------------------
 *
 */
package ae.pcfc.etks.online.common.delegate.provider;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import ae.pcfc.etks.online.common.delegate.ClientRegistrationDelegate;
import ae.pcfc.etks.online.common.domain.ServiceRole;
import ae.pcfc.etks.online.common.exception.AdminWorkflowException;
import ae.pcfc.etks.online.common.exception.DuplicateUserNameException;
import ae.pcfc.etks.online.common.facade.AppMetaDataFacade;
import ae.pcfc.etks.online.common.facade.ClientRegistrationFacade;
import ae.pcfc.etks.online.common.manager.MailManager;
import ae.pcfc.etks.online.common.vo.AdminApprovalVO;
import ae.pcfc.etks.online.common.vo.AppMetaDataDetailVO;
import ae.pcfc.etks.online.common.vo.ClientCompanyReqVO;
import ae.pcfc.etks.online.common.vo.ClientCompanyVO;
import ae.pcfc.etks.online.common.vo.ClientEmailVO;
import ae.pcfc.etks.online.common.vo.ClientPersonReqVO;
import ae.pcfc.etks.online.common.vo.ClientPersonVO;
import ae.pcfc.etks.online.common.vo.ClientRoleVO;
import ae.pcfc.etks.online.common.vo.CompanyDetailVO;
import ae.pcfc.etks.online.common.vo.SCCompanyVO;
import ae.pcfc.etks.online.common.vo.SCPersonVO;
import ae.pcfc.etks.online.common.vo.SearchCriteriaCompanyVO;
import ae.pcfc.etks.online.common.vo.SearchCriteriaPersonVO;
import ae.pcfc.etks.online.common.vo.TrakheesIdAndPINVO;
import ae.pcfc.etks.online.common.vo.UserVO;
import ae.pcfc.etks.online.wf.ConstantsWF;
import ae.pcfc.etks.online.wf.service.client.ClientAdminWF;
import ae.pcfc.etks.online.wf.service.client.ClientRoleWF;
import ae.pcfc.etks.online.wf.service.client.provider.ClientCompanyAdminWFImpl;
import ae.pcfc.etks.online.wf.service.client.provider.ClientPersonAdminWFImpl;
import ae.pcfc.etks.online.wf.service.client.vo.ClientAdminLaunchIncidentVO;
import ae.pcfc.etks.online.wf.service.client.vo.ClientRoleCompleteStepVO;
import ae.pcfc.etks.online.wf.service.client.vo.ClientRoleLaunchIncidentVO;
import ae.pcfc.etks.online.wf.service.client.vo.CompleteStepVO;

public class ClientRegistrationDelegateImpl extends BaseDelegateImpl implements
		ClientRegistrationDelegate, Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 6011101130354583416L;

	/*
	 * Here we coordinate between the Facade service which handles DB entities
	 * and the WF both will be looked up with service locator normally we will
	 * have 1-1 relationship between the delegate and the facade and 1-1
	 * relationship between the delegate and the WF service which means for
	 * CompanyRegistrationDelegate there will be ClientRegistrationFacade &
	 * CompanyRegistrationWF validations that related to DB vs WF are maintained
	 * here ie user cannot issue a new request while he already have a request
	 * in the wf Exception are translated in to business exception
	 */
	/**
	 * 
	 */
	public ClientRegistrationDelegateImpl() {

	}

	/**
	 * registerPerson
	 * 
	 * @see ae.pcfc.etks.online.common.delegate.ClientRegistrationDelegate#registerPerson(ae.pcfc.etks.online.common.vo.ClientPersonReqVO)
	 * 
	 */
	public String registerPerson(ClientPersonReqVO clientPersonReqVO) {

		// return
		// serviceLocator.getFacadeService(ClientRegistrationFacade.class).registerPerson(clientPersonReqVO);
		String clientReferenceNumber = null;
		ClientRegistrationFacade clientRegistrationFacade = serviceLocator
				.getFacadeService(ClientRegistrationFacade.class);
		AppMetaDataFacade appMetaDataFacade = serviceLocator
				.getFacadeService(AppMetaDataFacade.class);
		ClientAdminWF clientAdminWF = serviceLocator
				.getWorkflowService(ClientPersonAdminWFImpl.class);
		if (clientRegistrationFacade.validateRegisterPerson(clientPersonReqVO)) {
			String applicationID = appMetaDataFacade.getNextApplicationId();
			clientPersonReqVO.setStrApplicationId(applicationID);

			ClientAdminLaunchIncidentVO launchIncidVO = new ClientAdminLaunchIncidentVO();
			launchIncidVO.setgApplicationID(applicationID);
			clientRegistrationFacade.updatePersonWorkflowIncidentVO(
					launchIncidVO, clientPersonReqVO.getStrTrakheesId());
			Integer wfIncidentId = clientAdminWF
					.launchClientAdminWF(launchIncidVO);

			try {
				clientPersonReqVO.setStrWFIncidentId(wfIncidentId.toString());
				clientReferenceNumber = clientRegistrationFacade
						.registerPerson(clientPersonReqVO);
			} catch (RuntimeException t) {
				CompleteStepVO completeStepVO = new CompleteStepVO();
				completeStepVO
						.setStrUserName(ConstantsWF.ULTIMUS_DEFAULT_INITIATOR_NAME);
				completeStepVO.setnIncidentNumber(wfIncidentId);
				completeStepVO.setStrSummary(ConstantsWF.ROLLBACK_INCIDENT);
				clientAdminWF.abortIncident(completeStepVO);
				throw t;
			}
		}
		return clientReferenceNumber;

	}

	/**
	 * loadCompany
	 * 
	 * @see ae.pcfc.etks.online.common.delegate.ClientRegistrationDelegate#loadCompany(java.lang.String)
	 * 
	 */
	public CompanyDetailVO loadCompany(String id) {
		// TODO Auto-generated method stub
		return null;

	}

	/**
	 * validateTrakheesIdAndPIN
	 * 
	 * @see ae.pcfc.etks.online.common.delegate.ClientRegistrationDelegate#validateTrakheesIdAndPIN(ae.pcfc.etks.online.common.vo.TrakheesIdAndPINVO)
	 * 
	 */
	public boolean validateTrakheesIdAndPIN(TrakheesIdAndPINVO idAndPINVO) {

		return serviceLocator.getFacadeService(ClientRegistrationFacade.class)
				.validateTrakheesIdAndPIN(idAndPINVO);
	}

	/**
	 * findSCPersonByTrakheesId
	 * 
	 * @see ae.pcfc.etks.online.common.delegate.ClientRegistrationDelegate#findSCPersonByTrakheesId(java.lang.String)
	 * 
	 */
	public SCPersonVO findSCPersonByTrakheesId(String trakheesId) {
		return serviceLocator.getFacadeService(ClientRegistrationFacade.class)
				.findSCPersonByTrakheesId(trakheesId);
	}

	/**
	 * findSCCompanyByTrakheesId
	 * 
	 * @see ae.pcfc.etks.online.common.delegate.ClientRegistrationDelegate#findSCCompanyByTrakheesId(java.lang.String)
	 * 
	 */
	public SCCompanyVO findSCCompanyByTrakheesId(String trakheesId) {
		return serviceLocator.getFacadeService(ClientRegistrationFacade.class)
				.findSCCompanyByTrakheesId(trakheesId);
	}

	/**
	 * registerCompany
	 * 
	 * @see ae.pcfc.etks.online.common.delegate.ClientRegistrationDelegate#registerCompany(ae.pcfc.etks.online.common.vo.ClientCompanyReqVO)
	 * 
	 */
	public String registerCompany(ClientCompanyReqVO clientCompanyReqVO) {
		// return
		// serviceLocator.getFacadeService(ClientRegistrationFacade.class).registerCompany(clientCompanyReqVO);
		String clientReferenceNumber = null;
		ClientRegistrationFacade clientRegistrationFacade = serviceLocator
				.getFacadeService(ClientRegistrationFacade.class);
		AppMetaDataFacade appMetaDataFacade = serviceLocator
				.getFacadeService(AppMetaDataFacade.class);
		ClientAdminWF clientAdminWF = serviceLocator
				.getWorkflowService(ClientCompanyAdminWFImpl.class);
		if (clientRegistrationFacade
				.validateRegisterCompany(clientCompanyReqVO)) {
			String applicationID = appMetaDataFacade.getNextApplicationId();
			clientCompanyReqVO.setStrApplicationId(applicationID);

			ClientAdminLaunchIncidentVO launchIncidVO = new ClientAdminLaunchIncidentVO();
			launchIncidVO.setgApplicationID(applicationID);
			clientRegistrationFacade.updateCompanyWorkflowIncidentVO(
					launchIncidVO, clientCompanyReqVO.getStrTrakheesId());
			Integer wfIncidentId = clientAdminWF
					.launchClientAdminWF(launchIncidVO);

			try {
				clientCompanyReqVO.setStrWFIncidentId(wfIncidentId.toString());
				clientReferenceNumber = clientRegistrationFacade
						.registerCompany(clientCompanyReqVO);
			} catch (RuntimeException t) {

				CompleteStepVO completeStepVO = new CompleteStepVO();
				completeStepVO
						.setStrUserName(ConstantsWF.ULTIMUS_DEFAULT_INITIATOR_NAME);
				completeStepVO.setnIncidentNumber(wfIncidentId);
				completeStepVO.setStrSummary(ConstantsWF.ROLLBACK_INCIDENT);
				clientAdminWF.abortIncident(completeStepVO);

				if (t.getCause() instanceof org.hibernate.exception.ConstraintViolationException) {
					org.hibernate.exception.ConstraintViolationException e = (org.hibernate.exception.ConstraintViolationException) t
							.getCause();
					if (e.getConstraintName().equalsIgnoreCase(
							"ETKS_ONLINE_DBA.T_ETKS_USER_REQ_USERNAME_UNI")) {
						throw new DuplicateUserNameException(
								clientCompanyReqVO.getStrUserName());
					}
				} else
					throw t;
			}
		}
		return clientReferenceNumber;
	}

	/**
	 * findClientPersonByUserName
	 * 
	 * @see ae.pcfc.etks.online.common.delegate.ClientRegistrationDelegate#findClientPersonByUserName(java.lang.String)
	 * 
	 */
	public ClientPersonVO findClientPersonByUserName(String userName) {

		return serviceLocator.getFacadeService(ClientRegistrationFacade.class)
				.findClientPersonByUserName(userName);
	}

	/**
	 * findClientCompanyByUserName
	 * 
	 * @see ae.pcfc.etks.online.common.delegate.ClientRegistrationDelegate#findClientCompanyByUserName(java.lang.String)
	 * 
	 */
	public ClientCompanyVO findClientCompanyByUserName(String userName) {
		return serviceLocator.getFacadeService(ClientRegistrationFacade.class)
				.findClientCompanyByUserName(userName);
	}

	/**
	 * updateClientPerson
	 * 
	 * @see ae.pcfc.etks.online.common.delegate.ClientRegistrationDelegate#updateClientPerson(ae.pcfc.etks.online.common.vo.UserVO)
	 * 
	 */
	public void updateClientPerson(UserVO userVO) {

		serviceLocator.getFacadeService(ClientRegistrationFacade.class)
				.updatePerson(userVO);

	}

	/**
	 * updateClientCompany
	 * 
	 * @see ae.pcfc.etks.online.common.delegate.ClientRegistrationDelegate#updateClientCompany(ae.pcfc.etks.online.common.vo.UserVO)
	 * 
	 */
	public void updateClientCompany(UserVO userVO) {

		serviceLocator.getFacadeService(ClientRegistrationFacade.class)
				.updateCompany(userVO);

	}

	/**
	 * findTrakheesIdByUserName
	 * 
	 * @see ae.pcfc.etks.online.common.delegate.ClientRegistrationDelegate#findTrakheesIdByUserName(java.lang.String)
	 * 
	 */
	public String findTrakheesIdByUserName(String userName) {

		return serviceLocator.getFacadeService(ClientRegistrationFacade.class)
				.findTakheesIdByUserName(userName);
	}

	/**
	 * findPersonAvailableRoleByUserName
	 * 
	 * @see ae.pcfc.etks.online.common.delegate.ClientRegistrationDelegate#findPersonAvailableRoleByUserName(java.lang.String)
	 * 
	 */
	public List<ClientRoleVO> findPersonAvailableRoleByUserName(
			String strUserName) {

		return serviceLocator.getFacadeService(ClientRegistrationFacade.class)
				.findPersonAvailableRoleByUserName(strUserName);
	}

	/**
	 * addClientRoleReq
	 * 
	 * @see ae.pcfc.etks.online.common.delegate.ClientRegistrationDelegate#addClientRoleReq(java.lang.String,
	 *      java.util.List, ae.pcfc.etks.online.common.vo.AppMetaDataDetailVO)
	 * 
	 */
	public String addClientRoleReq(String strUserName, List<Long> roleIds,
			AppMetaDataDetailVO appMetaDataVO) {
		String clientReferenceNumber = null;
		ClientRegistrationFacade clientRegistrationFacade = serviceLocator
				.getFacadeService(ClientRegistrationFacade.class);
		AppMetaDataFacade appMetaDataFacade = serviceLocator
				.getFacadeService(AppMetaDataFacade.class);
		ClientRoleWF clientRoleWF = serviceLocator
				.getWorkflowService(ClientRoleWF.class);
		String applicationID = appMetaDataFacade.getNextApplicationId();
		appMetaDataVO.setStrApplicationId(applicationID);

		// Initiate the Workflow for approval
		ClientRoleLaunchIncidentVO launchIncidVO = new ClientRoleLaunchIncidentVO();
		launchIncidVO.setgApplicationID(applicationID);
		List<String> strRoleIds = new ArrayList<String>();
		if (roleIds != null) {
			for (Long roleId : roleIds) {
				strRoleIds.add(roleId.toString());
			}
		}
		clientRegistrationFacade.updateWorkflowIncidentVO(launchIncidVO,
				strRoleIds);
		Integer wfIncidentId = clientRoleWF.launchNonClientWF(launchIncidVO);

		try {
			appMetaDataVO.setStrWFIncidentId(wfIncidentId.toString());
			clientReferenceNumber = clientRegistrationFacade.addClientRoleReq(
					strUserName, roleIds, appMetaDataVO);
		} catch (RuntimeException t) {
			CompleteStepVO completeStepVO = new CompleteStepVO();
			completeStepVO
					.setStrUserName(ConstantsWF.ULTIMUS_DEFAULT_INITIATOR_NAME);
			completeStepVO.setnIncidentNumber(wfIncidentId);
			completeStepVO.setStrSummary(ConstantsWF.ROLLBACK_INCIDENT);
			clientRoleWF.abortIncident(completeStepVO);
			throw t;
		}

		return clientReferenceNumber;

	}

	/**
	 * findClientReqRoleByApplicationId
	 * 
	 * @see ae.pcfc.etks.online.common.delegate.ClientRegistrationDelegate#findClientReqRoleByApplicationId(java.lang.String)
	 * 
	 */
	public List<ClientRoleVO> findClientReqRoleByApplicationId(
			String applicationId) {

		return serviceLocator.getFacadeService(ClientRegistrationFacade.class)
				.findClientReqRoleByApplicationId(applicationId);
	}

	/**
	 * reviewClientRoleRequest
	 * 
	 * @see ae.pcfc.etks.online.common.delegate.ClientRegistrationDelegate#reviewClientRoleRequest(ae.pcfc.etks.online.common.vo.AdminApprovalVO)
	 * 
	 */
	public void reviewClientRoleRequest(AdminApprovalVO adminApprovalVO) {
		ClientRegistrationFacade clientRegistrationFacade = serviceLocator
				.getFacadeService(ClientRegistrationFacade.class);
		List<ServiceRole> returnServiceRoles = new ArrayList<ServiceRole>();
		ClientRoleCompleteStepVO completeStepVO = clientRegistrationFacade
				.reviewClientRoleRequest(adminApprovalVO, returnServiceRoles);
		try {
			ClientRoleWF clientRoleWF = serviceLocator
					.getWorkflowService(ClientRoleWF.class);
			clientRoleWF.completeNonClientWFStep(completeStepVO);
		} catch (Throwable t) {
			clientRegistrationFacade.undoReviewClientRoleRequest(
					adminApprovalVO, returnServiceRoles);
			throw new AdminWorkflowException(t);
		}
	}

	/**
	 * findTrakheesIdByApplicationId
	 * 
	 * @see ae.pcfc.etks.online.common.delegate.ClientRegistrationDelegate#findTrakheesIdByApplicationId(java.lang.String)
	 * 
	 */
	public String findTrakheesIdByApplicationId(String applicationId) {
		return serviceLocator.getFacadeService(ClientRegistrationFacade.class)
				.findTrakheesIdByApplicationId(applicationId);
	}

	/**
	 * recallClientTrakheesID
	 * 
	 * @see ae.pcfc.etks.online.common.delegate.ClientRegistrationDelegate#recallClientTrakheesID(ae.pcfc.etks.online.common.vo.ClientEmailVO)
	 * 
	 */
	public void recallClientTrakheesID(ClientEmailVO clientEmail) {
		// TODO check if the cleint email is right from the DB

		this.getServiceLocator()
				.getManager(MailManager.class)
				.sendMail(clientEmail.getStrEmailAddress(),
						clientEmail.getStrEmailSubject(),
						clientEmail.getStrEmailBody(), null);
	}

	/**
	 * findTrakheesIdAndPinByEmail
	 * 
	 * @see ae.pcfc.etks.online.common.delegate.ClientRegistrationDelegate#findTrakheesIdAndPinByEmail(java.lang.String)
	 * 
	 */
	public TrakheesIdAndPINVO findTrakheesIdAndPinByEmail(String email) {

		return this.serviceLocator.getFacadeService(
				ClientRegistrationFacade.class).findTrakheesIdAndPinByEmail(
				email);
	}

	/**
	 * findTrakheesIdAndPinByLicenseInfo
	 * 
	 * @see ae.pcfc.etks.online.common.delegate.ClientRegistrationDelegate#findTrakheesIdAndPinByLicenseInfo(ae.pcfc.etks.online.common.vo.SearchCriteriaCompanyVO)
	 * 
	 */
	public TrakheesIdAndPINVO findTrakheesIdAndPinByLicenseInfo(
			SearchCriteriaCompanyVO searchCriteriaCompanyVO) {
		return this.serviceLocator.getFacadeService(
				ClientRegistrationFacade.class)
				.findTrakheesIdAndPinByLicenseInfo(searchCriteriaCompanyVO);
	}

	public List<ClientRoleVO> findCurrentRolesByUserName(String strUserName) {
		return serviceLocator.getFacadeService(ClientRegistrationFacade.class)
				.findCurrentRolesByUserName(strUserName);
	}

	public List<SCCompanyVO> findCompany(
			SearchCriteriaCompanyVO searchCriteriaCompanyVO) {
		return serviceLocator.getFacadeService(ClientRegistrationFacade.class)
				.findCompany(searchCriteriaCompanyVO);
	}

	public List<SCPersonVO> findPerson(
			SearchCriteriaPersonVO searchCriteriaPersonVO) {
		return serviceLocator.getFacadeService(ClientRegistrationFacade.class)
				.findPerson(searchCriteriaPersonVO);
	}

}
